package charts ;

import charts.series.Element;
import charts.Base;
import charts.Base.DISTANCESTRUCT;
import string.Utils;
import global.Global;
import ColorConverter.Color;

typedef BARBASESTRUCT = {
	var values	: Array<Dynamic>;
	var color	: Color;
	var text	: String;
	var font_size	: Int;
	var tip		: String;
	var alpha	: Float;
	var onclick	: Dynamic; // TODO - check if this is the correct type
	var axis	: String;
};

/*
/// NOTE: already defined in Base
typedef DISTANCESTRUCT = {
	var element	: Element;
	var distance_x  : Float;
	var distance_y	: Float;
};
*/

class BarBase extends Base
{
	var group: Float;
	var style: BARBASESTRUCT;
	
	public function new ( json: Dynamic, group: Float )
	{
		super();		
		this.style = 
		{
			values:				[],
			color:				Hex('#3030d0'),
			text:				'',		// <-- default not display a key
			font_size:			12,
			tip:				'#val#<br>#x_label#',
			alpha:				0.6,
			onclick:			null,
			axis:				'left'	
		};
		
		ObjectHelper.merge_2( json, this.style );
		
		this.color	= ColorConverter.toInt( this.style.color );
		this.key	= this.style.text;
		this.font_size	= this.style.font_size;

		// Minor hack, replace all #key# with this key text:
		this.style.tip = StringTools.replace(style.tip,'#key#', this.key);
		
		//
		// bars are grouped, so 3 bar sets on one chart
		// will arrange them selves next to each other
		// at each value of X, this.group tell the bar
		// where it is in that grouping
		//
		this.group = group;
		
		this.values = this.style.values;
		this.add_values();
	}
	
	public override function resize ( sc:ScreenCoordsBase ): Void {
		
		for ( i in 0...this.numChildren )
		{
			var e:Element = cast(this.getChildAt(i),Element);
			e.resize( sc );
		}
	}
	
	
	public override function get_max_x(): Float {
		
		var max_index: Float = Math.NEGATIVE_INFINITY;
		
		for ( i in 0...this.numChildren ) {
			
			var e:Element = cast(this.getChildAt(i),Element);
			max_index = Math.max( max_index, e.index );
		}
		
		// 0 is a position, so count it:
		return max_index;
	}
	
	public override function get_min_x(): Float {
		return 0;
	}
	
	//
	// override or don't call this if you need better help
	//
	function get_element_helper( value: Dynamic ): BARBASESTRUCT {
		
		var default_style: BARBASESTRUCT = {
			color:		this.style.color,
			tip:		this.style.tip,
			alpha:		this.style.alpha,
			onclick:	this.style.onclick,
			axis:		this.style.axis
		};
		
		if(Std.is(value,Float))
			default_style.top = value;
		else
			ObjectHelper.merge_2( value, default_style );
			
		// our parent color is a number, but
		// we may have our own color:
		//if(Std.is(default_style.color,String )) // NOTE: this problem has been attacked with Enum type Color
			//default_style.color = Utils.get_color( default_style.color );
		
		// tr.ace_json(default_style);
		return default_style;
	}
	
	
	/*
			
			+-----+
			|  B  |
		+-----+     |   +-----+
		|  A  |     |   |  C  +- - -
		|     |     |   |     |  D
		+-----+-----+---+-----+- - -
				1   2
		
	*/
		
	
	public override function closest ( x: Float, y: Float ): DISTANCESTRUCT {
		var shortest: Float = Math.POSITIVE_INFINITY;
		var ex:Element = null;
		
		for ( i in 0...this.numChildren )
		{
			var e:Element = cast(this.getChildAt(i),Element);

			e.is_tip = false;
			
			if( (x > e.x) && (x < e.x+e.width) )
			{
				// mouse is in position 1
				shortest = Math.min( Math.abs( x - e.x ), Math.abs( x - (e.x+e.width) ) );
				ex = e;
				/* break */
			}
			else
			{
				// mouse is in position 2
				// get distance to left side and right side
				var d1: Float = Math.abs( x - e.x );
				var d2: Float = Math.abs( x - (e.x+e.width) );
				var min: Float = Math.min( d1, d2 );
				if( min < shortest )
				{
					shortest = min;
					ex = e;
				}
			}
		}
		var dy: Float = Math.abs( y - ex.y );
		
		return { element:ex, distance_x:shortest, distance_y:dy };
	}
}
